package com.saas.ability.core.base.view;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 缓存模版视图
 *
 *
 */
public abstract class AbstractCachingViewResolver implements ViewResolver {
	
	protected Logger logger = LoggerFactory.getLogger(AbstractCachingViewResolver.class);
	
	/**
	 * 最大缓存的模版视图实例
	 */
	public static final int DEFAULT_CACHE_LIMIT = 1024;

	private final Map<String, View> viewAccessCache = new ConcurrentHashMap<>(DEFAULT_CACHE_LIMIT);
	
	private Lock lock = new ReentrantLock();
	
	
	@Override
	public View resolveViewName(String viewName, String tplContent, Long lastTime) {
		if(lastTime == null || lastTime <= 0){
			//如果不提供 lastTime,则不缓存模版
			return createView(tplContent,null);
		}
		View view = getView(viewName,lastTime);
		if (view == null ) {
			try {
				if(lock.tryLock(10, TimeUnit.MILLISECONDS)){
					view = getView(viewName,lastTime);
					if (view == null) {
						view = createView(tplContent,lastTime);
						this.viewAccessCache.put(viewName, view);
					}
				}
			} catch (Exception e) {
				logger.error("创建视图异常,error:{}",e.getMessage());
			}finally{
				lock.unlock();
			}
		}
		return view;
	}

	@Override
	public View resolveViewName(String viewName,String tplContent){
		return resolveViewName(viewName,tplContent,null);
	}
	
	
	/**
	 * 创建视图
	 * @param viewName
	 * @return
	 */
	protected abstract View createView(String tplContent,Long lastTime);
	
	
	protected String getCacheKey(String viewName) {
		return viewName;
	}
	
	/**
	 * 检查是否需要创建View
	 * @param lastTime
	 * @return
	 */
	public View getView (String viewName,long updateTime) {
		View view = this.viewAccessCache.get(viewName);
		if(view != null){
			Long lastTime = view.getLastTime();
			if(lastTime != null && updateTime == lastTime){
				//模版没有被变更过
				return view;
			}
		}
		return null;
	}
}
